<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <div id="app">
    <p>content: {{content}}</p>
    <p>_data.content: {{_data.content}}</p>
    <p>_uid: {{_uid}}</p>
    <p>test(): {{test()}}</p>
    <p>test2(): {{test2()}}</p>
  </div>

  <script src="../js/vue.js"></script>
  <script>
    /* 
    模板能访问vue实例自身或原型链上的所有属性或方法
    data对象中的属性数据, 模板为什么能访问?
    */


    const vue = new Vue({
      // el: '#app',
      data: {
        content: 'hello'
      }
    })
    console.log(Vue)
    console.log(vue)
    console.log(vue._uid) // 读取vue实例自身的属性
    vue.test = () => {
      console.log('vue.test()')
      return 'vue的test方法返回值'
    }
    vue.__proto__.test2 = () => {
      return ' vue.__proto__的test方法返回值'
    }

    // 必须最后挂载
    vue.$mount('#app')

    /* 
    当读取content属性时, 内部会调用其getter
    而getter会读取并返回data对象中对应的属性值
    */
    console.log(vue.content)  // hello

    setTimeout(() => {
      /* 
      会触发对应的setter调用
      而setter中, 会将最新的值保存给data对象中的对应属性
      */
      vue.content = 'yes'
    }, 2000);

    /* 
    数据代理: 通过vue实例来代理对内部的data对象数据的操作
      当我们通过vue实例来读取数据时, 由于代理的存在, 最终读取的是data对象中的数据
      当我们通过vue实例来修改数据时, 由于代理的存在, 最终会将数据保存到data对象中
    有什么用?
      简化编码
    内部如何实现?
      通过defineProperty给vue实例添加data中对应的属性, 为每个属性都指定getter和setter
      在getter中, 读取data对象中的对应属性值返回
      在setter中, 将最新值保存到data对象的对应属性上

      vue实例来代理对data对象中数据的读写操作
    */
    const myVue = {
      _data: {
        msg: 'abc'
      }
    }
    // 没有代理
    // myVue._data.msg

    // 实现代理
    Object.defineProperty(myVue, 'msg', {
      get () { // 读取data对象中的对应属性值返回
        return this._data['msg']
      },
      set (value) { // 将最新值保存到data对象的对应属性上
        this._data['msg'] = value
      }
    })

    // 有代理后
    console.log(myVue.msg) // abc
    myVue.msg = 'cba'
    console.log(myVue._data.msg) // cba
  </script>
</body>
</html>